/**
 * @Description 初始化字典
 * @Author 莫发达
 * @create 2024-09-18 17:02 周二
 */

import { cache } from 'sf-utils2'
import dictApi from '@/api/modules/dict'
import type { IDict, IDictItem, DictKeys } from '@root/types/system/dict.ts'
import { ElMessage } from 'element-plus'
import localDict from '@/utils/origin-dict'
import { $enums } from '@/utils/enums.ts'

export type IDictKeys = DictKeys | keyof typeof localDict

export type IDictKeysInit = '@init' // 获取所有字典

export { $enums } from './enums.ts'

export { $param, $paramString, $paramBoolean, $paramJSON, $paramJSONArray, $initParam } from './param.ts'

/**
 * 字典
 */
let DICT = cache.getItem('DICT') || []

/**
 * 原始字典对象
 */
const ORIGIN_DICT: Record<string, IDictItem[]> = {}

/**
 * 启用的字典对象
 */
const ENABLE_DICT: Record<string, IDictItem[]> = {}

/**
 * 初始化字典
 */
export async function initDict() {
  // 检查全局缓存是否存在字典
  const cachedDict = window.$zsamcVars?.DICT

  if (cachedDict) {
    DICT = cachedDict
    cache.setItem('DICT', DICT)
    return DICT
  }

  try {
    let dictFromServer = cache.getItem('DICT')
    // 请求服务器获取字典
    if (!dictFromServer?.length) {
      dictFromServer = await fetchDictionaryFromServer()
    }

    cache.setItem('DICT', dictFromServer)
    DICT = dictFromServer

    // 初始化原始字典
    const originDict = processOriginalDictionary(dictFromServer)
    Object.assign(ORIGIN_DICT, localDict, originDict)

    // 初始化启用字典
    const enabledDict = processEnabledDictionary(dictFromServer)
    Object.assign(ENABLE_DICT, localDict, enabledDict)

    // debug
    // const dictKeys = generateDictKeys(dictFromServer)
    // console.log('dictKeys', dictKeys)

    return dictFromServer
  } catch (error) {
    console.error(error)
  }
}

/**
 * 从服务器请求字典数据
 * @returns 返回字典数组
 * @throws 当服务器响应码非200时抛出错误
 */
export async function fetchDictionaryFromServer(): Promise<IDict[]> {
  const { code, message, data } = await dictApi.getAllDict()

  if (code !== 200) {
    ElMessage.error(message)
    throw new Error(message)
  }

  return data
}

/**
 * 处理原始字典数据
 * @param dict 字典数组
 * @returns 返回经过处理的字典
 */
function processOriginalDictionary(dict: IDict[]): Record<string, IDict[]> {
  return dict.reduce((acc, currentDict) => {
    const dictKey = processDictionaryKey(currentDict)
    acc[dictKey] =
      currentDict.children?.map((item) => ({
        key: item.dictItemCode,
        label: item.dictItemName,
        tag: item.dictItemTag?.split(',') ?? []
      })) ?? []
    return acc
  }, {})
}

/**
 * 处理字典键
 * @param dict
 */
function processDictionaryKey(dict: IDict): string {
  // return dict.dictCode.startsWith('$') ? dict.dictCode : '$' + dict.dictCode
  return dict.dictCode
}

/**
 * 处理启用字典数据
 * @param dict 字典数组
 * @returns 返回经过处理的字典
 */
function processEnabledDictionary(dict: IDict[]): Record<string, IDict[]> {
  return (
    dict
      // 判断是否启用
      .filter((item) => item.enableFlag === $enums.enableFlag.ENABLE)
      .reduce((acc, currentDict) => {
        const dictKey = processDictionaryKey(currentDict)
        acc[dictKey] =
          currentDict.children
            // 判断是否启用
            ?.filter((item) => item.enableFlag === $enums.enableFlag.ENABLE)
            .map((item) => ({
              key: item.dictItemCode,
              label: item.dictItemName,
              tag: item.dictItemTag?.split(',') ?? []
            })) ?? []
        return acc
      }, {})
  )
}

// /**
//  * 生成字典键数组
//  * @param dict
//  */
// function generateDictKeys(dict: IDict[]): string {
//   return dict.map(({ dictCode, dictName }) => `| '${dictCode}' // ${dictName} `).join(' \n ')
// }

// eslint-disable-next-line no-redeclare
export function dict(dictKey: IDictKeys, opts?: { enable?: boolean }): IDictItem[]
// eslint-disable-next-line no-redeclare
export function dict(
  dictKey: IDictKeysInit,
  opts?: {
    enable?: boolean
  }
): Record<IDictKeys, IDictItem[]>
/**
 * 根据字典编码获取对应字典
 * @param dictKey 字典编码
 * @param options 选项，包含是否只获取启用的字典
 * @param options.enable 是否只获取启用的字典，默认为 true
 * @returns 返回字典项数组
 *
 * @example
 * // 获取启用的字典
 * const enabledDict = getDictionary('$userStatus'); // [{ key: 'active', label: 'Active' }, { key: 'inactive', label: 'Inactive' }]
 *
 * @example
 * // 获取所有字典（包括未启用的）
 * const allDict = getDictionary('$userStatus', { enable: false }); // [{ key: 'active', label: 'Active' }, { key: 'inactive', label: 'Inactive' }]
 */
// eslint-disable-next-line no-redeclare
export function dict(
  dictKey: IDictKeys | IDictKeysInit,
  { enable = true }: { enable?: boolean } = {}
): IDictItem[] | Record<IDictKeys, IDictItem[]> {
  // fix 如果是@init，那么将返回所有
  if (dictKey == '@init') return enable ? ENABLE_DICT : ORIGIN_DICT
  // 获取启用的字典或原始字典，若找不到则返回空数组
  return (enable ? ENABLE_DICT[dictKey] : ORIGIN_DICT[dictKey]) ?? []
}

/**
 * 根据字典编码和字典项编码获取字典项
 * @param dictKey 字典编码
 * @param key 字典项编码
 * @returns 返回匹配的字典项，如果未找到则返回 undefined
 *
 * @example
 * // 获取字典编码为 '$userStatus' 且字典项编码为 'active' 的字典项
 * const dictItem = getDictionaryItem('$userStatus', 'active'); // { key: 'active', label: 'Active' }
 *
 * @example
 * // 获取字典编码为 '$orderStatus' 且字典项编码为 'pending' 的字典项
 * const dictItem = getDictionaryItem('$orderStatus', 'pending'); // { key: 'pending', label: 'Pending' }
 */
export function dictItem(dictKey: IDictKeys | IDictItem[], key: string): IDictItem | undefined {
  const dictList = Array.isArray(dictKey) ? dictKey : ORIGIN_DICT[dictKey]

  // 获取匹配的字典项，若字典不存在则返回 undefined
  return dictList?.find((item) => item.key === key)
}

/**
 * 根据字典编码和字典项编码获取字典项标签
 * @param dictKey 字典数组或字典编码
 * @param keys 字典项编码或编码数组
 * @returns 返回匹配的字典项标签或标签数组
 *
 * @example
 * // 获取单个字典项标签
 * const label = getDictionaryLabel('user_status', 'active'); // 'Active'
 *
 * @example
 * // 获取多个字典项标签
 * const labels = getDictionaryLabel('user_status', ['active', 'inactive']); // ['Active', 'Inactive']
 *
 * @example
 * // 传入字典项数组直接获取标签
 * const dictItems: IDictItem[] = [
 *   { key: 'active', label: 'Active' },
 *   { key: 'inactive', label: 'Inactive' }
 * ];
 * const labelFromItems = getDictionaryLabel(dictItems, 'active'); // 'Active'
 * const labelsFromItems = getDictionaryLabel(dictItems, ['active', 'inactive']); // ['Active', 'Inactive']
 */
export function dictLabel(dictKey: IDictKeys | IDictItem[], keys: string): string | undefined
// eslint-disable-next-line no-redeclare
export function dictLabel(dictKey: IDictKeys | IDictItem[], keys: string[]): string[] | undefined
// eslint-disable-next-line no-redeclare
export function dictLabel(dictKey: IDictKeys | IDictItem[], keys: string | string[]): string | string[] | undefined {
  const dictList = Array.isArray(dictKey) ? dictKey : ORIGIN_DICT[dictKey]
  if (!dictList) return undefined

  const itemKeyList = Array.isArray(keys) ? keys : [keys]

  // 返回匹配的标签数组或单个标签
  const labels = dictList?.filter((item) => itemKeyList.includes(item.key)).map((item) => item.label)
  return Array.isArray(keys) ? labels : labels?.[0]
}

/**
 * 根据字典编码和过滤器获取过滤后的字典项
 * @param dict 字典编码
 * @param filter 过滤器函数，用于过滤字典项，返回 `true` 的项将被保留
 * @param opts 选项，包含是否只获取启用的字典
 * @returns 返回过滤后的字典项数组
 *
 * @example
 * // 获取状态为启用的字典项
 * const enabledItems = filterDict('user_status', (item) => item.status === 'enabled');
 *
 * @example
 * // 获取标签包含 'important' 的字典项
 * const importantItems = filterDict('task_priority', (item) => item.tag.includes('important'));
 */
export function dictFilter(
  dict: IDictKeys,
  filter: (item: IDictItem) => boolean,
  opts?: {
    enable?: boolean
  }
): IDictItem[] {
  // 使用传入的过滤器函数过滤字典项，若字典不存在则返回空数组
  return $dict(dict, opts)?.filter(filter) ?? []
}

/**
 * 初始化字典
 * @description 初始化全局字典数据，并缓存到本地存储
 */
export const $initDict = initDict

/**
 * 获取字典
 * @description 根据字典编码获取字典项列表
 */
export const $dict = dict

/**
 * 获取字典项标签
 * @description 根据字典编码和字典项编码获取对应的字典项标签
 */
export const $dictLabel = dictLabel

/**
 * 获取字典项
 * @description 根据字典编码和字典项编码获取具体的字典项
 */
export const $dictItem = dictItem

/**
 * 过滤字典
 * @description 根据字典编码和过滤器函数获取过滤后的字典项列表
 */
export const $dictFilter = dictFilter
